Verilog-A 语法基础
语法简单而严格。熟悉 C/C++/Perl 者上手快;函数使用受多种限制,代码行为更依赖仿真器而非解释器。
注释
// 单行注释
/* 多行
注释 */
多行注释在特殊字符上可能引起问题,优先用
//。
命名规则
- 由数字 + 字母 + 下划线组成,首字符必须是字母或下划线。
- 可用反斜杠转义命名(如
\inputA),除代码加密外无使用价值。 V和G是保留关键字(常被默认为电源/地端口),不能用作端口名。- 命名应表达功能:如
PeakCurrentDetector、adc_8bit,避免aaa/bbb。
数字常量
整数(十进制):100、9;二进制 'b011x11、'b0010100010
浮点:1e6(科学计数法)、1.34e2
工程单位字符(数量级):
| 字符 | 倍数 | 字符 | 倍数 | |
|---|---|---|---|---|
| T | 10¹² | m | 10⁻³ | |
| G | 10⁹ | u | 10⁻⁶ | |
| M | 10⁶ | n | 10⁻⁹ | |
| K / k | 10³ | p | 10⁻¹² | |
| f | 10⁻¹⁵ | |||
| a | 10⁻¹⁸ |
用法:1K、10M、1p、1n
字符串
- Verilog-A 中一般变量不能存储字符串;字符串多为常量或来自文件读取。
- 主要用在
$strobe/$display等调试语句内。 - Verilog-AMS 数字域可用 reg 保存:
reg [8*12:1] stringvar;
换行与分号
- 每条语句以
;结束,换行会被自动忽略。 - 长语句可换行书写,阅读性更好:
if(V(out, gnd)>vth) begin
xout=1;
yout=V(out, gnd);
end
空白
- 空白(空格/Tab/换行)用作变量、运算符之间的分隔。
- 注意不能插在格式符中间,如
%d不能写成% d。
运算符优先级
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 1(最高) | + - ! ~ & ~& | ~| ^ ^~ |
一元运算符 |
| 2 | * / % |
乘除取余 |
| 3 | + - |
加减 |
| 5 | < > <= >= |
关系 |
| 6 | == != === !== | 相等(含 X/Z 判断用 =/!) |
| 7 | & |
按位与 |
| 8 | ^ ^~ |
按位异或/同或 |
| 9 | | |
按位或 |
| 10 | && |
逻辑与 |
| 11(最低) | || |
逻辑或 |
完整运算符细节见 04 - VerilogA 运算符。
包含外部文件(编译器指令)
`include "constants.vams"
`include "disciplines.vams"
- ` 是键盘 Tab 上方的反引号,不是单引号。
constants.vams:常用数值常量,如`define M_PI 3.14159265358979323846。disciplines.vams:discipline 定义,核心是electrical:
discipline electrical
potential Voltage ;
flow Current ;
enddiscipline
- Cadence 环境默认导入这两个文件;其他平台可能是
constants.h/disciplines.h。 - 其他编译器指令见 11 - VerilogA 自定义函数与编译器指令。
模拟过程(analog 块)
所有模拟行为代码放在 analog begin ... end 之间:
analog begin
V(P ,N) <+ I(P, N)*R; // 电阻描述
end
V:电压。单端点=对地电压;双端点=两点电位差。I:电流。单端点=流入该点的总电流(流入为正);双端点=两点间电流。- 每个模块只能有一个 analog 块。
赋值:= 与 <+ 的本质区别
| 运算符 | 用途 | 计算方式 | 叠加性 |
|---|---|---|---|
| = | integer/real 变量赋值 | 直接计算,无需迭代 | 覆盖:R=R1; R=R2; → R=R2 |
<+ |
模拟量(V/I)贡献 | 仿真器迭代求解的方程 | 叠加:多个 <+ 对同一量求和 |
V(P,N) <+ V1;
V(P,N) <+ V2; // 结果 V(P,N) = V1 + V2
<+只能出现在 analog 块内;= 几乎可用在任何位置。
条件与循环语句
if 语句
if (X)
A;
else if (Y)
B;
else
C;
- 多语句用 begin-end 包裹;else 匹配最近的 if,建议每个 if 都配 else(可用空
;)。
if (X) begin
A; B;
end else begin
C;
end
case 语句
case(value)
(1) : A;
(2) : B;
default : D;
endcase
- 也可反用:
case(1)内放条件 (X)(Y)(Z) 分别执行 A/B/C,等效多个 if。
循环语句
// for(不支持 i++,必须 i = i + 1)
for (i = 1; i < 10; i = i + 1) total = total + i;
// while
i = 1;
while (i < 10) begin
i = i + 1;
total = total + i;
end
// repeat(次数必须为常数,不适用模拟变量)
repeat (9) begin
i = i + 1;
total = total + i;
end
genvar 与总线循环
普通 integer 循环不能访问总线端口(仿真器无法在编译期展开):
genvar i; // ✅ 用 genvar
for (i = 1; i < 10; i = i + 1)
V(out[i]) <+ V(in[i]);
- genvar 仅用于 analog 块内,且只能由常数或其他 genvar 赋值/修改。
实战提示
- 多用乘法少用除法:
V(P,N) <+ I(P,N)*R;优于I(P,N) <+ V(P,N)/R;——R=0 时除法易出问题。 - 端口按信号流定义
input/output/inout,模拟端口声明electrical。 - 总线端口:
input [1:12] bus; electrical [1:12] bus;,访问bus[1]。
相关笔记
- 数据类型 → 03 - VerilogA 数据类型与变量
- 运算符详解 → 04 - VerilogA 运算符
- 模块结构 → 05 - VerilogA 模块定义与实例化
- 模拟事件 → 06 - VerilogA 模拟事件